home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 10 / FM Towns Free Software Collection 10.iso / ms_dos / tool / dprint / fselect.c < prev    next >
Text File  |  1994-08-11  |  8KB  |  373 lines

  1. /*
  2.  
  3. ファイルセレクタルーチン
  4.  
  5. Copyleft 1994 Delmonta
  6. このソースファイルは自由に再利用してかまいません。
  7.  
  8. */
  9.  
  10. #include<stdio.h>
  11. #include<string.h>
  12. #include<jstring.h>
  13. #include<ctype.h>
  14. #include<stdlib.h>
  15. #include<dos.h>
  16. #include<direct.h>
  17. #include<setjmp.h>
  18. #include"dprint.h"
  19.  
  20. /*-------------------------------マクロ定義----------------------------------*/
  21. #define    ONELINE        5        /* 1行に表示するファイルの数        */
  22. #define    LINENUM        5        /* ファイル表示部の行数             */
  23. #define    STARTPOS    SYSLINE_START    /* ファイルセレクタエィンドウ表示開始行         */
  24. #define    SPACENUM    ((78-12*ONELINE)/(ONELINE-1))
  25.                     /* 行中のファイルの間のスペースの数 */
  26. /*--------------------------------型と変数-----------------------------------*/
  27. static    struct DIRCHAIN
  28. {
  29.     char        name[13];
  30.     int        attr;
  31.     unsigned    date;
  32.     unsigned    time;
  33.     long        size;
  34.     struct DIRCHAIN    *prev;
  35.     struct DIRCHAIN    *next;
  36.  
  37. } **Dir = NULL;
  38.  
  39. static    char    Path[64];
  40. static    int    Drive;
  41.  
  42. static    int    Offset,Pos;
  43. static    int    Dirnum;
  44.  
  45. static    jmp_buf    Jmp_buf;
  46. /*--------------------------ディレクトリ検索ルーチン-------------------------*/
  47. static    struct DIRCHAIN    *opndir(char *path, char attr)
  48. {
  49.     char        *chp;
  50. static    struct find_t    fib;
  51.     struct DIRCHAIN    *dirtop;
  52.     struct DIRCHAIN    *dir;
  53.     static char    buf[FILENAME_MAX];
  54.  
  55.     strncpy(buf, path, FILENAME_MAX - 1);
  56.     chp = strchr(buf,'\0') -1;
  57.  
  58.     if (*chp==':' || *chp=='\\')
  59.         strncat(buf, "*.*", FILENAME_MAX - 1);
  60.  
  61.     if    (_dos_findfirst(buf, attr, &fib))
  62.         return NULL;
  63.  
  64.     if ((dir = dp_malloc(sizeof(struct DIRCHAIN))) == NULL)
  65.         return NULL;
  66.  
  67.     dirtop = dir;
  68.     dir->prev = NULL;
  69.     strcpy(dir->name, fib.name);
  70.     dir->attr = fib.attrib;
  71.     dir->time = fib.wr_time;
  72.     dir->date = fib.wr_date;
  73.     dir->size = fib.size;
  74.     dir->next = NULL;
  75.     while (_dos_findnext(&fib) == 0)
  76.     {
  77.         if ((dir->next = dp_malloc(sizeof(struct DIRCHAIN))) == NULL)
  78.             return dirtop;
  79.  
  80.         dir->next->prev = dir;
  81.         dir = dir->next;
  82.         strcpy(dir->name, fib.name);
  83.         dir->attr = fib.attrib;
  84.         dir->time = fib.wr_time;
  85.         dir->date = fib.wr_date;
  86.         dir->size = fib.size;
  87.         dir->next = NULL;
  88.     }
  89.     return dirtop;
  90. }
  91. /*---------------指定されたディレクトリを検索して配列に展開------------------*/
  92. static    void    dirfree(void)
  93. {
  94.     int    i;
  95.  
  96.     for    (i=0 ; i<Dirnum ; i++)
  97.         free(Dir[i]);
  98.  
  99.     free(Dir);
  100.     Dir = NULL;
  101. }
  102.  
  103. static    int    cmp(struct DIRCHAIN **a,struct DIRCHAIN **b)
  104. {
  105.     int    p = ((*a)->attr & _A_SUBDIR);
  106.     int    q = ((*b)->attr & _A_SUBDIR);
  107.  
  108.     if    (p && !q)    return -1;    /* ディレクトリはそれ以外の */
  109.     else if    (!p && q)    return 1;    /* ファイルより優先         */
  110.  
  111.     p = ((*a)->name[0]=='.');
  112.     q = ((*b)->name[0]=='.');
  113.  
  114.     if    (p && !q)    return -1;    /* 先頭の"." ".." 対策 */
  115.     else if    (!p && q)    return 1;
  116.     else if    (p && q)
  117.     {
  118.         if    ((*a)->name[1]=='.')    return 1;
  119.         else                return 0;
  120.     }
  121.     else
  122.         return strcmp((*a)->name,(*b)->name);
  123. }
  124.  
  125. static    void    scan(void)
  126. {
  127.     struct DIRCHAIN    *d1,*d2;
  128.     int    i;
  129.  
  130.     if    (Dir!=NULL)
  131.         dirfree();
  132.  
  133.     Dirnum = 0;
  134.     d1 = opndir(Path,_A_SUBDIR);
  135.  
  136.     if    (d1==NULL)    /* ルートに何もない場合を考慮 */
  137.     {
  138.         d1 = dp_malloc(sizeof(struct DIRCHAIN));
  139.         if    (d1==NULL)
  140.             longjmp(Jmp_buf,1);
  141.  
  142.         d1->name[0] = '.';
  143.         d1->name[1] = '\0';
  144.         d1->attr = _A_SUBDIR;
  145.         d1->next = NULL;
  146.     }
  147.  
  148.     for    (d2=d1 ; d2!=NULL ; d2=d2->next)
  149.         Dirnum++;
  150.  
  151.     Dir = dp_malloc(sizeof(struct DIRCHAIN *)*Dirnum);
  152.     if    (Dir==NULL)
  153.         longjmp(Jmp_buf,1);
  154.  
  155.     for    (d2=d1,i=0 ; i<Dirnum ; i++,d2=d2->next)
  156.         Dir[i] = d2;
  157.  
  158.     qsort(Dir,Dirnum,sizeof(Dir[0]),(int(*)(const void*,const void*))cmp);
  159. }
  160. /*--------------------------------画面の初期化-------------------------------*/
  161. static    void    openwindow(void)
  162. {
  163.     printf("\033[%d;1f"
  164.            "─────────────────ファイル選択─────────────────"
  165.            "\033[%d;1f"
  166.            "────────────────────────────────────────"
  167.         "ファイル名 \n"
  168.            "────────────────────────────────────────"
  169.            "ドライブ変更:[TAB]",STARTPOS,STARTPOS+LINENUM+1);
  170. }
  171.  
  172. static    void    closewindow(void)
  173. {
  174.     int    i;
  175.  
  176.     dirfree();
  177.     printf("\033[%d;1f",STARTPOS);
  178.     for    (i=0 ; i<=LINENUM+4 ; i++)
  179.         printf("\033[2K\n");
  180. }
  181. /*------------------------画面へのファイル名の表示---------------------------*/
  182. void    putfile(int pos)
  183. {
  184.     printf("\033[%d;%df",(pos-Offset)/ONELINE+STARTPOS+1,
  185.                 3+pos%ONELINE*(12+SPACENUM));
  186.  
  187.     if    (pos>=Dirnum)
  188.     {
  189.         printf("%14s","");
  190.         return;
  191.     }
  192.  
  193.     if    (Dir[pos]->attr & _A_SUBDIR)    putchar('<');
  194.     else                    putchar(' ');
  195.  
  196.     if    (Pos==pos)
  197.         printf("\033[7m");
  198.  
  199.     printf("%-12s\033[0m",Dir[pos]->name);
  200.  
  201.     if    (Dir[pos]->attr & _A_SUBDIR)    putchar('>');
  202.     else                    putchar(' ');
  203.  
  204.     if    (Pos==pos)
  205.         printf("\033[%d;%df\033[33m%s%s\033[0K\033[37m",
  206.             STARTPOS+LINENUM+2,12,Path,Dir[pos]->name);
  207. }
  208.  
  209. void    putpage()
  210. {
  211.     int    i;
  212.     for    (i=0 ; i<ONELINE*LINENUM ; i++)
  213.         putfile(Offset+i);
  214. }
  215. /*-----------------------------ドライブの変更--------------------------------*/
  216. bool    isdriveexist(char drv)    /* drvは大文字と仮定 */
  217. {
  218.     int    a,b;
  219.  
  220.     drv = drv-'A'+1;
  221.  
  222.     _dos_getdrive(&a);
  223.  
  224.     _dos_setdrive(drv,&b);
  225.     _dos_getdrive(&b);
  226.  
  227.     if    (b!=drv)
  228.         return FALSE;
  229.  
  230.     _dos_setdrive(a,&b);
  231.     return TRUE;
  232. }
  233.  
  234. void    get_current_directory(char drv,char *path)
  235. {
  236.     union    REGS    reg;
  237.  
  238.     reg.h.ah = 0x47;
  239.     reg.h.dl = drv-'A'+1;
  240.     reg.x.si = (unsigned)path;
  241.     intdos(®,®);
  242. }
  243.  
  244. void    input_driveno(void)
  245. {
  246.     char    c;
  247.  
  248.     printf("\033[%d;1f\033[2Kドライブ名:",STARTPOS+LINENUM+2);
  249. rep:
  250.     c = dp_getch();
  251.     if    (!isalpha((unsigned char)c) || !isdriveexist(c=toupper(c)))
  252.     {
  253.         putchar('\a');
  254.         goto rep;
  255.     }
  256.  
  257.     Path[0] = c;
  258.     Path[1] = ':';
  259.     Path[2] = '\\';
  260.     get_current_directory(c,Path+3);
  261.     if    (Path[3]!='\0')
  262.         strcat(Path,"\\");
  263.  
  264.     printf("\033[%d;1f\033[2Kファイル名 ",STARTPOS+LINENUM+2);
  265. }
  266. /*-------------------------------メインルーチン------------------------------*/
  267. FILE    *fileselector(char *mode,char *name)
  268. {
  269.     char    c;
  270.  
  271.     if    (setjmp(Jmp_buf)==1)
  272.         return NULL;
  273.  
  274.     getcwd(Path,sizeof(Path)-1);
  275.     if    (strchr(Path,'\0')[-1]!='\\')
  276.         strcat(Path,"\\");
  277.  
  278.     openwindow();
  279. restart:
  280.     scan();
  281.     Offset = Pos = 0;
  282.     putpage();
  283. keyrep:
  284.     c = dp_getch();
  285.     if    (c==EXTKEY_H)    /* 特殊キーは捨てる */
  286.     {
  287.         dp_getch();
  288.         goto keyrep;
  289.     }
  290.     if    (c=='\t')        /* HT:ドライブの変更 */
  291.     {
  292.         input_driveno();
  293.         goto restart;
  294.     }
  295.     else if    (c=='\033')        /* ESC:中断 */
  296.     {
  297.         closewindow();
  298.         return NULL;
  299.     }
  300.                     /* CR:ディレクトリ移動 */
  301.     else if    (c=='\r' && (Dir[Pos]->attr & _A_SUBDIR))
  302.     {
  303.         if    (Dir[Pos]->name[0]=='.')
  304.         {
  305.             if    (Dir[Pos]->name[1]=='\0')
  306.                 goto keyrep;
  307.             else
  308.             {
  309.                 *jstrrchr(Path,'\\') = '\0';
  310.                 jstrrchr(Path,'\\')[1] = '\0';
  311.             }
  312.         }
  313.         else                    /* サブディレクトリ */
  314.         {
  315.             strcat(Path,Dir[Pos]->name);
  316.             strcat(Path,"\\");
  317.         }
  318.  
  319.         goto restart;
  320.     }
  321.             /* CR/文字キー:キーボードからのファイル名入力モード */
  322.     else if    (c=='\r' || !iscntrl((unsigned char)c))
  323.     {
  324.         char    buf[64];
  325.         strcpy(buf,Path);
  326.  
  327.         if    (c=='\r')
  328.             strcat(buf,Dir[Pos]->name);
  329.         else
  330.             dp_ungetch(c);
  331.  
  332.         printf("\033[%d;%df",STARTPOS+LINENUM+2,12);
  333.  
  334.         if    (strinput(buf,sizeof(buf)))
  335.         {
  336.             FILE    *fp = fopen(buf,mode);
  337.             if    (fp!=NULL)
  338.             {
  339.                 if    (name!=NULL)
  340.                     strcpy(name,buf);
  341.  
  342.                 closewindow();
  343.                 return fp;
  344.             }
  345.  
  346.             dp_errmes("ファイルがオープンできません");
  347.         }
  348.         putfile(Pos);
  349.     }
  350.     else
  351.     {
  352.         int    p = Pos;
  353.  
  354.         switch    (c)
  355.         {
  356.         case UPKEY:    if (Pos>=ONELINE)    Pos-=ONELINE;    break;
  357.         case DOWNKEY:    if (Pos+ONELINE<Dirnum) Pos+=ONELINE;    break;
  358.         case LEFTKEY:    if (Pos>0)        Pos--;        break;
  359.         case RIGHTKEY:    if (Pos+1<Dirnum)    Pos++;        break;
  360.  
  361.         default:    putchar('\a');    break;
  362.         }
  363.  
  364.         if    (Pos<Offset)            /* 上へスクロール */
  365.             Offset-=ONELINE,putpage();
  366.         else if    (Pos>=Offset+ONELINE*LINENUM)    /* 下へスクロール */
  367.             Offset+=ONELINE,putpage();
  368.         else    if    (p!=Pos)    /* 反転するファイルの変更のみ */
  369.             putfile(p),putfile(Pos);
  370.     }
  371.     goto keyrep;
  372. }
  373.